/** 
 * @description 对象数组转对象
 * @param {Array} arr 目标数组
 * @param {string} key 对象的 key 对应的数组元素的 key
 * @param {string} value 对象的 value 对应的数组元素的 value
 * @returns {Object}
 */

export const arrToObj = (arr:Array<any>, key:any, value:any) => {
  let obj:any = {}

  Array.isArray(arr) && arr.forEach((item:any) => {
    obj[item[key]] = item[value]
  })

  return obj
}

/**
 * @description 校验某个值是否为空
 * @param {*} val
 * @returns {boolean} 返回该值是否为空
 */
export const isEmpty = (val:any) => {
  // null, undefined
  if (val == null) return true

  if (typeof val === 'boolean') return false

  // 0 不视为空
  if (typeof val === 'number') return false

  // Error 对象的 `message` 属性是否为空
  // see: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError
  if (val instanceof Error) return val.message === ''

  switch (getRawType(val)) {
    // String, Array
    case 'String':
    case 'Array':
    return !val.length

    // Set, Map, File
    case 'Set':
    case 'Map':
    case 'File':
    return !val.size

    // 纯对象
    case 'Object':
    return !Object.keys(val).length
  }

  return false
}
/**
 * @desc 获取给定变量的原始类型字符串，[[Class]]: [object Object] => Object
 * @param {*} value - 给定变量
 * @return {String} 返回给定变量的原始类型的小写形式，e.g. getRawType(new Date) return 'date'
 */
export const getRawType = (value:any) => {
  return toString.call(value).slice(8, -1).toLowerCase()
}

/**
 * @desc 节流函数
 * @author Monkey Chen
 * @param {Function} fn - 需要节流的函数
 * @param {Number} wait - 等待时间，毫秒
 * @return {Function} 返回实际调用的函数
 */
export const throttle = (fn:any, wait:number) => {
  // 上一次执行 `fn` 的时间
  let lastTime = 0

  return (...args:any) => {
    let now = +new Date()
    // 如果当前时间与上一次执行时间的间隔大于等待时间，则执行函数
    if (now - lastTime > wait) {
      lastTime = now
      fn.apply(this, args)
    }
  }
}

/**
* @desc 去抖函数
* @author Monkey Chen
* @param {Function} fn - 需要去抖的函数
* @param {Number} delay - 延迟时长，毫秒
* @return {Function} 返回实际调用的函数
*/
export const debounce = (fn:any, delay:number) => {
  let timer:any = null // 定时器标志

  return (...args:any) => {
    // 清空定时器
    if (timer) clearTimeout(timer)

    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}